require 'ping'

require 'rubygems'
require 'yaml'
require 'net/smtp'
require 'erb'
require 'tempfile'


module ClientException
  #Class Name:PropertyNotFoundException
  #Custom Exception  to indicate missing fields in the config file.
  class PropertyNotFoundException < StandardError
  end
end

# An helper class which helps to send email notification of the Ping Report
# Uses Ruby's built in Free SMTP library.
class EmailNotifier
  # * Description*
  # * Create a instance of EmailNotifier
  # * Parameters*
  # * log: refernce to logger instance
  # * Returns*
  # * reference to Email Notifier instance
  # * Exception Raises*
  # * None  
  def initialize
  end
  
  # * Description*
  # * The method to send  email notification
  # * Parameters*
  # * host: Host of the mail server
  # * port: port for sending email
  # * username: valid username for authentication
  # * password: valid password for authencation
  # * domain: domain name
  # * Returns*
  # * None
  # * Exception Raises*
  # * None  
  def send_email_msg(host, port, domain, username, password, from, to, error_message)
      Net::SMTP.start(host, port, domain, username, password, :login) do |smtp|
      smtp.send_message error_message, from, [to]
    end
  end

  # * Description*
  # * The method to create a message format for email
  # * Parameters*
  # * from: email address of the user from which email notification is been sent.
  # * to: destination email addresss.
  # * subject: Subject for the email
  # * message: Message body of the email
  # * Returns*
  # * None
  # * Exception Raises*
  # * None  
def create_formatted_message(from, to, subject, message)
    formattedMessage = <<END_OF_MESSAGE
From: #{from}
To: #{to.join(";")}
Subject: #{subject}

#{message}
END_OF_MESSAGE
    return formattedMessage
end

  # * Description*
  # * This method reads smtp configuration from the smpt_settings.yml file.
  # * Parameters*
  # * path: path to the smpt_settings.yml file.
  # * Returns*
  # * None
  # * Exception Raises*
  # * PropertyNotFoundException
  def read_smtp_configuration(smtp_settings_path)
    begin
      smtp_configuration = YAML::load(File.read(smtp_settings_path))
      smtp_settings = smtp_configuration["smtp_settings"]
      raise PropertyNotFoundException,'smtp_settings Entry missing in smtp_settings config file' if (smtp_settings.nil? || smtp_settings.eql?(""))          
      host = smtp_settings["host"]
      raise PropertyNotFoundException,'host Entry missing in smtp_settings config file' if  (host.nil? || host.eql?(""))          
      port = smtp_settings["port"]
      raise PropertyNotFoundException,'port Entry missing in smtp_settings config file' if  (port.nil? || port.eql?(""))          
      domain = smtp_settings["domain"]
      raise PropertyNotFoundException,'domain Entry missing in smtp_settings config file' if  (domain.nil? || domain.eql?(""))          
      username = smtp_settings["username"]
      raise PropertyNotFoundException,'username Entry missing in smtp_settings config file' if  (username.nil? || username.eql?(""))         
      password = smtp_settings["password"]
      raise PropertyNotFoundException,'password Entry missing in smtp_settings config file' if (password.nil? || password.eql?(""))          
      from = smtp_settings["from"]
      raise PropertyNotFoundException,'from Entry missing in smtp_settings config file' if (from.nil? || from.eql?(""))          
      to = smtp_settings["to"]
      raise PropertyNotFoundException,'to Entry missing in smtp_settings config file' if (to.nil? || to.eql?(""))
      to = to.split(";")

    rescue PropertyNotFoundException => pnf
          puts "Error message while reading smtp_settings.yml file"
          puts "#{pnf.class} - #{pnf.message}"
          Process.exit
      rescue Exception => e
          puts "Error message while reading smtp_settings.yml file"
          puts "#{e.class} - #{e.message}"
          Process.exit
      
    end
    smtp_configuration
  end
end


class RubyPing
  INPUT_YAML = 'hostnames.yml'
  OUTPUT_FILE = 'PingStatus.txt'
  
  def initialize
    @email_notifier = EmailNotifier.new
    smtp_configuration = @email_notifier.read_smtp_configuration('smtp_settings.yml')
    @host = smtp_configuration["smtp_settings"]["host"]
    @port = smtp_configuration["smtp_settings"]["port"]
    @domain = smtp_configuration["smtp_settings"]["domain"]
    @username = smtp_configuration["smtp_settings"]["username"]
    @password = smtp_configuration["smtp_settings"]["password"]
    @from = smtp_configuration["smtp_settings"]["from"]
    @to = smtp_configuration["smtp_settings"]["to"].split(";")
  end

  def check_status(host,timeout=10, port=80)
    return Ping.pingecho(host,timeout, port)
  end

  def pingall
    message_body = []
    hostnames = YAML::load(File.read(INPUT_YAML))
    hostnames['projects'].each_key do |project|
      message_body << "\n\n----------------------------------------------------"
      message_body << "\nPROJECT -> #{project}\n"
      message_body << "----------------------------------------------------\n"
      hostnames['projects'][project]['users'].each_key do |user|
        message_body << "#{Time.now} | #{user} | #{check_status(hostnames['projects'][project]['users'][user])}\n"
        message_body << "----------------------------------------------------\n"
      end
    end
    msg = @email_notifier.create_formatted_message(@from, @to, 'Machine ON/OFF Status Report', message_body.to_s)
    @email_notifier.send_email_msg(@host, @port, @domain, @username, @password, @from, @to, msg)
  end
end

RubyPing.new.pingall
